﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using QuickGraph;
using System.IO;

namespace DeadlockDetection
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        private IBidirectionalGraph<object, IEdge<object>> processedGraph;
        /*public IBidirectionalGraph<object, IEdge<object>> GraphToVisualize
        {
            get { return _graphToVisualize; }
        }*/

        public Processes processes;
        public Resources resources;

        public int numberOfResources = 5;
        public int numberOfProcesses = 4;
        public int maxInstancesOfResource = 5;

        //public int currentPreparedInstanceS = -1;
        //public int currentPreparedInstanceM = -1;

        public Window1()
        {
            InitializeComponent();
            singleInstanceSimplifyGraphButton.IsEnabled = false;
            singleResourceDeadlockDetectionButton.IsEnabled = false;
            multipleResourceDeadlockDetectionButton.IsEnabled = false;
        }

        private void CreateGraphToVisualize()
        {
            if (processes == null || resources == null) return;

            var g = new BidirectionalGraph<object, IEdge<object>>();

            string[] processVertices = new string[processes.Length];
            string[] resourceVertices = new string[resources.Length];
            
            for (int i = 0; i < resources.Length; i++)
            {
                resourceVertices[i] = resources[i].ToString();
                //if(processVertexPresent[i]) 
                //    g.AddVertex(resourceVertices[i]);
            }

            for (int i = 0; i < processes.Length; i++)
            {
                processVertices[i] = processes[i].ToString();
                //if (resourceVertexPresent[i]) 
                //    g.AddVertex(processVertices[i]);
            }

            //g.AddVerticesAndEdge(

            for (int i = 0; i < processes.Length; i++)
            {
                for (int j = 0; j < resources.Length; j++)
                {
                    if (processes[i].resourcesAllocated[j] > 0)
                    {
                        g.AddVerticesAndEdge(new Edge<object>(resourceVertices[j], processVertices[i]));
                        //g.AddEdge(new Edge<object>(resourceVertices[j], processVertices[i]));
                    }

                    if (processes[i].resourcesRequested[j] > 0)
                    //    && processes[i].resourcesRequested[j] > processes[i].resourcesAllocated[j])
                    {
                        g.AddVerticesAndEdge(new Edge<object>(processVertices[i], resourceVertices[j]));
                        //g.AddEdge(new Edge<object>(processVertices[i], resourceVertices[j]));
                    }
                }
            }

            processedGraph = g;
            DataContext = g;
        }

        private void CreateSimplifiedGraphToVisualize()
        {
            if (processes == null || resources == null) return;

            var g = new BidirectionalGraph<object, IEdge<object>>();

            string[] processVertices = new string[processes.Length];
            string[] resourceVertices = new string[resources.Length];
            List<int>[] processedConnectedWithResource = new List<int>[resources.Length]; 

            for (int i = 0; i < resources.Length; i++)
            {
                resourceVertices[i] = resources[i].ToString();
                processedConnectedWithResource[i] = new List<int>();
            }

            for (int i = 0; i < processes.Length; i++)
            {
                processVertices[i] = processes[i].ToString();
            }

            for (int i = 0; i < processes.Length; i++)
            {
                for (int j = 0; j < resources.Length; j++)
                {
                    if (processes[i].resourcesAllocated[j] > 0)
                    {
                        processedConnectedWithResource[j].Add(i);
                    }
                }
            }

            for (int i = 0; i < processes.Length; i++)
            {
                for (int j = 0; j < resources.Length; j++)
                {
                    if (processes[i].resourcesRequested[j] > 0)
                    //    && processes[i].maxResourcesNeeded[j] > processes[i].resourcesAllocated[j])
                    {
                        foreach(int index in processedConnectedWithResource[j])
                        {
                            g.AddVerticesAndEdge(new Edge<object>(processVertices[i], processVertices[index]));
                        }
                    }
                }
            }

            processedGraph = g;
            DataContext = g;
        }

        private void singleResourceGenerateRandomInstanceButton_Click(object sender, RoutedEventArgs e)
        {
            resultTextBox.Clear();
            resources = new Resources(numberOfResources);
            processes = new Processes(numberOfProcesses, resources, true);
            CreateGraphToVisualize();
            singleInstanceSimplifyGraphButton.IsEnabled = true;
        }

        private void singleResourceInstancePickComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // wybór gotowej instancji - pojedyncze zasoby
            resultTextBox.Clear();
            int instancePicked = singleResourceInstancePickComboBox.SelectedIndex + 1;

            FileStream fileStream = new FileStream("Instances/s" + instancePicked + ".txt", FileMode.Open, FileAccess.Read, FileShare.Read);
            StreamReader fileReader = new StreamReader(fileStream);

            fileReader.ReadLine();
            string buf = fileReader.ReadLine();
            buf.Trim();
            string[] fields = buf.Split(' ');

            int numberOfProcesses = Convert.ToInt32(fields[0]);
            int numberOfPResources = Convert.ToInt32(fields[1]);

            resources = new Resources(fileReader, numberOfPResources);
            processes = new Processes(fileReader, numberOfProcesses);

            fileReader.Close();
            CreateGraphToVisualize();
            singleInstanceSimplifyGraphButton.IsEnabled = true;
        }

        private void singleResourceDeadlockDetectionButton_Click(object sender, RoutedEventArgs e)
        {
            // wykrycie deadlocka - pojedyncze zasoby
            BidirectionalGraph<object, IEdge<object>> g = (BidirectionalGraph<object, IEdge<object>>)processedGraph;
            Algorithms algorithms = new Algorithms();
            bool isDeadlocked = algorithms.Graphs(g, processes.Length);

            if(isDeadlocked) resultTextBox.AppendText("Istnieje zakleszczenie!");
            else resultTextBox.AppendText("Brak deadlocków.");
            singleResourceDeadlockDetectionButton.IsEnabled = false;
        }

        private void multipleResourceGenerateRandomInstanceButton_Click(object sender, RoutedEventArgs e)
        {
            resultTextBox.Clear();
            resources = new Resources(numberOfResources, maxInstancesOfResource);
            processes = new Processes(numberOfProcesses, resources);
            CreateGraphToVisualize();
            multipleResourceDeadlockDetectionButton.IsEnabled = true;
        }

        private void multipleResourceInstancePickComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // wybór gotowej instancji - wiele instancji zasobu
            resultTextBox.Clear();
            int instancePicked = multipleResourceInstancePickComboBox.SelectedIndex + 1;

            FileStream fileStream = new FileStream("Instances/m" + instancePicked + ".txt", FileMode.Open, FileAccess.Read, FileShare.Read);
            StreamReader fileReader = new StreamReader(fileStream);

            fileReader.ReadLine();
            string buf = fileReader.ReadLine();
            buf.Trim();
            string[] fields = buf.Split(' ');

            int numberOfProcesses = Convert.ToInt32(fields[0]);
            int numberOfPResources = Convert.ToInt32(fields[1]);

            resources = new Resources(fileReader, numberOfPResources);
            processes = new Processes(fileReader, numberOfProcesses);

            fileReader.Close();
            CreateGraphToVisualize();
            multipleResourceDeadlockDetectionButton.IsEnabled = true;
        }

        private void multipleResourceDeadlockDetectionButton_Click(object sender, RoutedEventArgs e)
        {
            Algorithms algorithms = new Algorithms();
            List<int> deadlockedProcesses = algorithms.Banker(processes, resources);
            if (deadlockedProcesses.Count == 0)
            {
                resultTextBox.AppendText("Brak deadlocków!");
            }
            else
            {
                foreach (int deadlocked in deadlockedProcesses)
                {
                    resultTextBox.AppendText("P" + deadlocked + ", ");
                }
            }
            multipleResourceDeadlockDetectionButton.IsEnabled = false;
        }

        private void singleInstanceSimplifyGraphButton_Click(object sender, RoutedEventArgs e)
        {
            CreateSimplifiedGraphToVisualize();
            singleInstanceSimplifyGraphButton.IsEnabled = false;
            singleResourceDeadlockDetectionButton.IsEnabled = true;
        }

        private void relayoutButton_Click(object sender, RoutedEventArgs e)
        {
            graphLayout.Relayout();
        }
    }
}
